package main

import (
	"config"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
	"os"
	"sort"
	"strconv"
	"strings"
	"time"
	"util"
)

/**
 *
 * @return
 */
func api_email_send(c *gin.Context) {
	if _code, _msg, _ok := config.Send(); !_ok {
		c.JSON(http.StatusOK, gin.H{
			"error": gin.H{
				"code": _code, //
				"msg":  _msg,
			},
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"time": time.Now().UnixNano() / 1e6,
	})
}

/**
 *
 * @return
 */
func api_email_sendByTLS(c *gin.Context) {
	// 参数验证
	_signature, _to, _subject, _body, _ok := params(c)
	if !_ok {
		c.JSON(http.StatusOK, gin.H{
			"error": gin.H{
				"code": "2413", // 参数验证失败
			},
		})
		return
	}

	// 时间戳验证
	if _ok := ts(c); !_ok {
		c.JSON(http.StatusOK, gin.H{
			"error": gin.H{
				"code": "2412", // 时间戳验证失败
			},
		})
		return
	}

	//
	_appkey := c.Query("appkey")
	_orz, _ok := config.GetAuth(&_appkey)
	if !_ok {
		c.JSON(http.StatusOK, gin.H{
			"error": gin.H{
				"code": "invalid_client",
			},
		})
		return
	}

	// 签名验证
	if _ok := checkSign(c, _signature, _orz.Pass); !_ok {
		c.JSON(http.StatusOK, gin.H{
			"error": gin.H{
				"code": "2414", // 签名验证失败
			},
		})
		return
	}

	if _code, _msg, _ok := config.SendByTLS(_orz.Host, _orz.Port, _orz.From, _orz.Nickname, _orz.Pass, _to, _subject, _body); !_ok {
		c.JSON(http.StatusOK, gin.H{
			"error": gin.H{
				"code": _code, //
				"msg":  _msg,
			},
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"time": time.Now().UnixNano() / 1e6,
	})
}

/**
 *
 * @return
 */
func params(c *gin.Context) (w, x, y, z string, b bool) {
	_signature := c.Query("signature")
	_signature = strings.Trim(_signature, " ")
	if 1 > len(_signature) {
		return "", "", "", "", false
	}

	_to := c.Query("to")
	_to = strings.Trim(_to, " ")
	if 1 > len(_to) {
		return "", "", "", "", false
	}

	_subject := c.Query("subject")
	_subject = strings.Trim(_subject, " ")
	if 1 > len(_subject) {
		return "", "", "", "", false
	}

	_content := c.Query("content")
	_content = strings.Trim(_content, " ")
	if 1 > len(_content) {
		return "", "", "", "", false
	}

	return _signature, _to, _subject, _content, true
}

/**
 * 时间戳
 *
 * @return
 */
func ts(c *gin.Context) bool {
	if "production" != os.Getenv("EMAIL_MODE") {
		return true
	}

	_ts := c.Query("ts")
	_n, _err := strconv.ParseInt(_ts, 10, 64)
	if nil != _err {
		return false
	}

	if _now := time.Now().UnixNano() / 1e6; _n < (_now-1000*180) || _n > (_now+1000*180) {
		return false
	}

	return true
}

/**
 *
 * @return
 */
func checkSign(c *gin.Context, signature, secKey string) (b bool) {
	_cc := c.Request.URL.Query()
	_cc.Del("signature")

	// 抽取参数
	var _keyS sort.StringSlice
	for _i := range _cc {
		_keyS = append(_keyS, _i)
	}

	sort.Sort(_keyS)

	// key及value拼接
	var _uri strings.Builder
	for _i := range _keyS {
		_key := _keyS[_i]
		_uri.WriteString(_key)
		_uri.WriteString(c.Query(_key))
	}

	// 生成签名
	_sign2 := util.GenSignature(secKey, _uri.String())

	if "development" == os.Getenv("EMAIL_MODE") {
		log.Println(_sign2, signature)
	}

	return signature == _sign2
}
